home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGBLER / A86V318B.LZH / A09.DOC < prev   
Text File  |  1988-05-20  |  26KB  |  611 lines

  1. CHAPTER 9   DIRECTIVES IN A86
  2.  
  3.  
  4. Segments in A86
  5.  
  6. The following discussion applies when A86 is assembling a .COM
  7. See the next chapter for the discussion of segmentation for .OBJ
  8. files.
  9.  
  10. A86 views the 86 computer's memory space as having two parts: The
  11. first part is the program, whose contents are the object bytes
  12. generated by A86 during its assembly of the source.   A86 calls
  13. this area the CODE SEGMENT.  The second part is the data area,
  14. whose contents are generated by the program after it starts
  15. running.  A86 calls this area the DATA SEGMENT.
  16.  
  17. Please note well that the only difference between the CODE and
  18. DATA segments is whether the contents are generated by the
  19. program or the assembler.  The names CODE and DATA suggest that
  20. program code is placed in the CODE segment, and data structures
  21. go in the DATA segment.  This is mostly true, but there are
  22. exceptions.  For example, there are many data structures whose
  23. contents are determined by the assembler: pointer tables, arrays
  24. of pre-defined constants, etc.  These tables are assembled in the
  25. CODE segment.
  26.  
  27. In general, you will want to begin your program with the
  28. directive DATA SEGMENT, followed by an ORG statement giving the
  29. address of the start of your data area.  You then list all your
  30. program variables and uninitialized data structures, using the
  31. directives DB, DW, and STRUC.  A86 will allocate space starting
  32. at the address given in the ORG statement, but it will not
  33. generate any object bytes in that space.  After your data segment
  34. declarations, you provide a CODE SEGMENT directive, followed by
  35. an ORG giving the address of the start of your program.  You
  36. follow this with the program itself, together with any
  37. assembler-generated data structures.  A short program
  38. illustrating this suggested usage follows:
  39.  
  40. DATA SEGMENT
  41. ORG 08000
  42.   ANSWER_BYTE  DB ?
  43.   CALL_COUNT   DW ?
  44.  
  45. CODE SEGMENT
  46.   JMP MAIN
  47.  
  48. TRAN_TABLE:
  49.   DB 16,3,56,23,0,9,12,7
  50.  
  51. MAIN:
  52.   MOV BX,TRAN_TABLE
  53.   XLATB
  54.   MOV ANSWER_BYTE,AL
  55.   INC CALL_COUNT
  56.   RET
  57.                                                               9-2
  58.  
  59. A86 allows you to intersperse CODE SEGMENTs and DATA SEGMENTs
  60. throughout your program; but in general it is best to put all
  61. your DATA SEGMENT declarations at the top of your program, to
  62. avoid problems with forward referencing.
  63.  
  64.  
  65. CODE ENDS and DATA ENDS Statements
  66.  
  67. For compatibility with Intel/IBM assemblers, A86 provides the
  68. CODE ENDS and DATA ENDS statements.  The CODE ENDS statement is
  69. ignored; we assume that you have not nested a CODE segment inside
  70. a DATA segment.  The DATA ENDS statement is equivalent to a CODE
  71. SEGMENT statement.
  72.  
  73.  
  74.  
  75. The ORG Directive
  76.  
  77. Syntax:  ORG address
  78.  
  79. ORG moves the output pointer (the location counter at which
  80. assembly is currently taking place within the current segment) to
  81. the value of the operand, which should be an absolute constant,
  82. or an expression evaluating to an absolute, non-forward-
  83. referenced constant.
  84.  
  85. ORG is most often used in a DATA segment, to control the location
  86. of the data area within the segment.  For example, in programs
  87. that fit entirely into 64K, you provide an ORG directive as the
  88. first line within your DATA segment at the top of your program.
  89. The location given by the ORG is some location that you are sure
  90. will be beyond the end of your program.  If you are sure that
  91. your program will not go beyond 8K (02000 hex), your program can
  92. look like this:
  93.  
  94. DATA SEGMENT
  95. ORG 02000       ; data goes here, beyond the end of the program
  96.  
  97. (your data segment variable and buffer declarations go here)
  98.  
  99. DATA ENDS
  100.  
  101. (your program goes here)
  102.                                                               9-3
  103.  
  104. There is a special side effect to ORG when it is used in the CODE
  105. segment.  If you begin your code segment with ORG 0, then A86
  106. knows that you are not assembling a .COM program; but are instead
  107. assembling a code segment to be used in some other context
  108. (examples: programming a ROM, or assembling a procedure for older
  109. versions of Turbo Pascal).  The output file will start at 0, not
  110. 0100 as in a .COM file; and the default extension for the output
  111. file will be .BIN, not .COM.
  112.  
  113. Other than in the above example, you should not in general issue
  114. an ORG within the CODE segment that would lower the value of the
  115. output pointer.  This is because you thereby put yourself in
  116. danger of losing part of your assembled program.  If you re-
  117. assemble over space you have already assembled, you will clobber
  118. the previously-assembled code.  Also, be aware that the size of
  119. the output program file is determined by the value of the code
  120. segment output pointer when the program stops.  If you ORG to a
  121. lower value at the end of your program, the output program file
  122. will be truncated to the lower-value address.
  123.  
  124. Again, almost no program producing a .COM file will need any ORG
  125. directive in the code segment.  There is an implied ORG 0100 at
  126. the start of the program.  You just start coding instructions,
  127. and the assembler will put them in the right place.
  128.  
  129.  
  130. The EVEN Directive
  131.  
  132. Syntax:  EVEN
  133.  
  134. The EVEN directive coerces the current output pointer to an even
  135. value.  In a DATA SEGMENT or STRUC, it does so by adding 1 to the
  136. pointer if the pointer was odd; doing nothing if the pointer was
  137. already even.  In a code segment, it outputs a NOP if DI was odd.
  138. EVEN is most often used in data segments, before a sequence of DW
  139. directives. The 16-bit machines of the 86 family fetch words more
  140. quickly when they are aligned onto even addresses; so the EVEN
  141. directive insures that your program will have the faster access
  142. to those DW's that follow it.  (This speed improvement will not
  143. be seen on the 8-bit machines, most notably the 8088 of the
  144. original IBM-PC.)
  145.  
  146.  
  147. Data Allocation Using DB, DW, DD, DQ, and DT
  148.  
  149. The 86 computer family supports the three fundamental data types
  150. BYTE, WORD, and DWORD. A byte is eight bits, a word is 16 bits (2
  151. bytes), and a doubleword is 32 bits (4 bytes).   In addition, the
  152. 87 floating point processor manipulates 8-byte quantities, which
  153. we call Q-words, and 10-byte quantities, which we call T-words.
  154. The A86 data allocation statement is used to specify the bytes,
  155. words, doublewords, Q-words, and T-words which your program will
  156. use as data. The syntax for the data allocation statement is as
  157. follows:
  158.                                                               9-4
  159.  
  160. (optional var-name)  DB  (list of values)
  161. (optional var-name)  DW  (list of values)
  162. (optional var-name)  DD  (list of values)
  163. (optional var-name)  DQ  (list of values)
  164. (optional var-name)  DT  (list of values)
  165.  
  166. The variable name, if present, causes that name to be entered
  167. into the symbol table as a memory variable with type BYTE (for
  168. DB), WORD (for DW), DWORD (for DD), QWORD (for DQ), or TBYTE (for
  169. DT). The variable name should NOT have a colon after it, unless
  170. you wish the name to be a label (instructions referring to it
  171. will interpret the label as the constant pointer to the memory
  172. location, not its contents).
  173.  
  174. The DB statement is used to reserve bytes of storage; DW is used
  175. to reserve words.  The list of values to the right of the DB or
  176. DW serves two purposes.  It specifies how many bytes or words are
  177. allocated by the statement, as well as what their initial values
  178. should be.  The list of values may contain a single value or more
  179. than one, separated by commas.  The list can even be missing;
  180. meaning that we wish to define a byte or word variable at the
  181. same location as the next variable.
  182.  
  183. If the data initialization is in the DATA segment, the values
  184. given are ignored, except as place markers to reserve the
  185. appropriate number of units of storage.  The use of "?", which in
  186. .COM mode is a synonym for zero, is recommended in this context
  187. to emphasize the lack of actual memory initialization. When A86
  188. is assembling .OBJ files, the ?-initialization will cause a break
  189. in the segment (unless ? is embedded in a nested DUP containing
  190. non-? terms, in which case it is a synonym for zero).
  191.  
  192. A special value which can be used in data initializations is the
  193. DUP construct, which allows the allocation and/or initialization
  194. of blocks of data.  The expression  n DUP x  is equivalent to a
  195. list with x repeated n times.  "x" can be either a single value,
  196. a list of values, or another DUP construct nested inside the
  197. first one.  The nested DUP construct needs to be surrounded by
  198. parentheses.  All other assemblers, and earlier versions of A86,
  199. require parentheses around all right operands to DUP, even simple
  200. ones; but this requirement has been removed for simple operands
  201. in the current A86.
  202.  
  203. Here are some examples of data initialization statements, with
  204. and without DUP constructs:
  205.  
  206. CODE SEGMENT
  207.   DW 5                  ; allocate one word, init. to 5
  208.   DB 0,3,0              ; allocate three bytes, init. to 0,3,0
  209.   DB 5 DUP 0            ; equivalent to DB 0,0,0,0,0
  210.   DW 2 DUP (0,4 DUP 7)  ; equivalent to DW 0,7,7,7,7,0,7,7,7,7
  211.                                                               9-5
  212.  
  213. DATA SEGMENT
  214. XX      DW ?            ; define a word variable XX
  215. YYLOW   DB              ; no init value: YYLOW is low byte of word var YY
  216. YY      DW ?
  217. X_ARRAY DB  100 DUP ?   ; X_ARRAY is a 100-byte array
  218. D_REAL  DQ ?            ; double precision floating variable
  219. EX_REAL DT ?            ; extended precision floating variable
  220.  
  221. A character string value may be used to initialize consecutive
  222. bytes in a DB statement.  Each character will be represented by
  223. its ASCII code.  The characters are stored in the order that they
  224. appear in the string, with the first character assigned to the
  225. lowest-addressed byte.  In the DB statement that follows, five
  226. bytes are initialized with the ASCII representation of the
  227. characters in the string 'HELLO':
  228.  
  229. DB 'HELLO'
  230.  
  231. Note that except for string comparisons described in the previous
  232. chapter, the DB directive is the only place in your program that
  233. strings of length greater than 2 may occur.  In all other
  234. contexts (including DW), a string is treated as the constant
  235. number representing the ASCII value of the string; for example,
  236. CMP AL,'@' is the instruction comparing the AL register with the
  237. ASCII value of the at-sign.  Note further that 2- character
  238. string constants, like all constants in the 8086, have their
  239. bytes reversed.  Thus, while DB 'AB' will produce hex 41 followed
  240. by hex 42, the similar looking DW 'AB' reverses the bytes: hex 42
  241. followed by hex 41.
  242.  
  243. For compatibility, A86 now accepts double quotes, as well as
  244. single quotes, for strings in DB directives.
  245.  
  246.  
  247. The DD directive is used to initialize 32-bit doubleword pointers
  248. to locations in arbitrary segments of the 86's memory space.
  249. Values for such pointers are given by two numbers separated by a
  250. colon.  The segment register value appears to the left of the
  251. colon; and the offset appears to the right of the colon.  In
  252. keeping with the reversed-bytes nature of memory storage in the
  253. 86 family, the offset comes first in memory.  For example, the
  254. statement
  255.  
  256.    DD   01234:05678
  257.  
  258. appearing in a CODE segment will cause the hex bytes 78 56 34 12
  259. to be generated, which is a long pointer to segment 01234, offset
  260. 05678.
  261.  
  262. DD, DQ, and DT can also be used to initialize large integers and
  263. floating point numbers.  Examples:
  264.  
  265.   DD 500000   ; half million, too big for most 86 instructions
  266.   DD 3.5      ; single precision floating point number
  267.   DQ 3.5      ; the same number in a double precision format
  268.   DT 3.5      ; the same number in an extended precision format
  269.                                                               9-6
  270.  
  271. The STRUC Directive
  272.  
  273. The STRUC directive is used to define a template of data to be
  274. addressed by one of the 8086's base and/or index registers.  The
  275. syntax of STRUC is as follows:
  276.  
  277. (optional strucname)  STRUC  (optional effective address)
  278.  
  279. The optional structure name given at the beginning of the line
  280. can appear in subsequent expressions in the program, with the
  281. operator TYPE applied to it, to yield the number of bytes in the
  282. structure template.
  283.  
  284. The STRUC directive causes the assembler to enter a mode similar
  285. to DATA SEGMENT: assembly within the structure declares symbols
  286. (the elements of the structure), using a location counter that
  287. starts out at the address following STRUC.  If no address is
  288. given, assembly starts at location 0.  An option not available to
  289. the DATA SEGMENT is that the address can include one base
  290. register [BX] or [BP] and/or one index register [SI] or [DI]. The
  291. registers are part of the implicit declaration of all structure
  292. elements, with the offset value increasing by the number of bytes
  293. allocated in each structure line. For example:
  294.  
  295. LINE STRUC [BP]        ; the template starts at [BP]
  296.        DB 80 DUP (?)   ; these 80 bytes advance us to [BP+80]
  297. LSIZE  DB ?            ; this 1 byte advnaces us to [BP+81]
  298. LPROT  DB ?
  299.      ENDS
  300.  
  301. The STRUC just given defines the variables LSIZE, equivalent to
  302. B[BP+80], and LPROT, equivalent to B[BP+81].  You can now issue
  303. instructions such as MOV AL,LSIZE; which automatically generates
  304. the correct indexing for you.
  305.  
  306. The mode entered by STRUC is terminated by the ENDS directive,
  307. which returns the assembler to whatever segment (CODE or DATA) it
  308. was in before the STRUC, with the location counter restored to
  309. its value within that segment before the STRUC was declared.
  310.  
  311.  
  312.  
  313. Forward References
  314.  
  315. A86 allows names for a variety of program elements to be forward
  316. referenced.  This means that you may use a symbol in one
  317. statement and define it later with another statement.  For
  318. example:
  319.  
  320.   JNZ TARGET
  321.   .
  322.   .
  323. TARGET:
  324.   ADD AX,10
  325.  
  326. In this example, a conditional jump is made to TARGET, a label
  327. farther down in the code.  When JNZ TARGET is seen, TARGET is
  328. undefined, so this is a forward reference.
  329.                                                               9-7
  330.  
  331. Earlier versions of A86 were much more restricted in the kinds of
  332. forward references allowed.  Most of the restrictions have now
  333. been eased, for convenience as well as compatibility with other
  334. assemblers.  In particular, you may now make forward references
  335. to variable names.  You just need to see to it that A86 has
  336. enough information about the type of the operand to generate the
  337. correct instruction.  For example, MOV FOO,AL will cause A86 to
  338. correctly deduce that FOO is a byte variable.  You can even code
  339. a subsequent MOV FOO,1 and A86 will remember that FOO was assumed
  340. to be a byte variable.  But if you code MOV FOO,1 first, A86
  341. won't know whether to issue a byte or a word MOV instruction; and
  342. will thus issue an error message.  You then specify the type by
  343. MOV FOO B,1.
  344.  
  345. In general, A86's compatibility with That Other assembler has
  346. improved dramatically for forward references.  Now, for most
  347. programs, you need only sprinkle a very few B's and W's into your
  348. references.  And you'll be rewarded: in many cases the word form
  349. is longer than the byte form, so that the other assembler winds
  350. up inserting a wasted NOP in your program.  You'll wind up with
  351. tighter code by using A86!
  352.  
  353.  
  354. Forward References in Expressions
  355.  
  356. A86 now allows you to add or subtract a constant number from a
  357. forward reference symbol; and to append indexing registers to a
  358. forward reference symbol.  This covers a vast majority of
  359. expressions formerly disallowed.  For the remaining, more
  360. complicated expressions, there is a trick you can use to work
  361. your way around almost any case where you might run into a
  362. forward reference restriction.  The trick is to move the
  363. expression evaluation down in your program so that it no longer
  364. contains a forward reference; and forward reference the
  365. evaluation answer.  For example, suppose you wish to advance the
  366. ES segment register to point immediately beyond your program. If
  367. PROG_SIZE is the number of bytes in your program, then you add
  368. (PROGSIZE+15)/16 to the program's segment register value. This
  369. value is known at assembly time; but it isn't known until the end
  370. of the program.  You do the following:
  371.  
  372.      MOV AX,CS        ; fetch the program's segment value
  373.      ADD AX,SEG_SIZE  ; use a simple forward reference
  374.      MOV ES,AX        ; ES is now loaded as desired
  375.  
  376. Then at the end of the program you evaluate the expression:
  377.  
  378.      PROG_SIZE EQU $
  379.      SEG_SIZE EQU (PROG_SIZE+15)/16
  380.                                                               9-8
  381.  
  382. The EQU Directive
  383.  
  384. Syntax:  symbol-name EQU expression
  385.          symbol-name EQU built-in-symbol
  386.          symbol-name EQU INT n
  387.  
  388. The expression field may specify an operand of any type that
  389. could appear as an operand to an instruction.
  390.  
  391. As a simple example, suppose you are writing a program that
  392. manipulates a table containing 100 names and that you want to
  393. refer to the maximum number of names throughout the source file.
  394. You can, of course, use the number 100 to refer to this maximum
  395. each time, as in MOV CX,100, but this approach suffers from two
  396. weaknesses.  First of all, 100 can mean a lot of things; in the
  397. absence of comments, it is not obvious that a particular use of
  398. 100 refers to the maximum number of names.  Secondly, if you
  399. extend the table to allow 200 names, you will have to locate each
  400. 100 and change it to a 200.  Suppose, instead, that you define a
  401. symbol to represent the maximum number of names with the
  402. following statement:
  403.  
  404. MAX_NAMES EQU 100
  405.  
  406. Now when you use the symbol MAX_NAMES instead of the number 100
  407. (for example, MOV CX,MAX_NAMES), it will be obvious that you are
  408. referring to the maximum number of names in the table.  Also, if
  409. you decide to extend the table, you need only change the 100 in
  410. the EQU directive to a 200 and every reference to MAX_NAMES will
  411. reflect the change.
  412.  
  413. You could also take advantage of A86's strong typing, by changing
  414. MAX_NAMES to a variable:
  415.  
  416. MAX_NAMES  DB ?
  417.  
  418. or even an indexed quantity:
  419.  
  420. MAX_NAMES EQU [BX+1]
  421.  
  422. Because the A86 language is strongly typed, the instruction for
  423. loading MAX_NAMES into the CX register remains exactly the same
  424. in all cases: simply MOV CX,MAX_NAMES.
  425.                                                               9-9
  426.  
  427. Equates to Built-In Symbols
  428.  
  429. A86 allows you to define synonyms for any of the assembler
  430. reserved symbols, by EQUating an alternate name of your choosing,
  431. to that symbol.  For example, suppose you were coding a source
  432. module that is to be incorporated into several different
  433. programs.  In some programs, a certain variable will exist in the
  434. code segment.  In others, it will exist in the stack segment. You
  435. want to address the variable in the common source module, but you
  436. don't know which segment override to use.  The solution is to
  437. declare a synonym, QS, for the segment register.  QS will be
  438. defined by each program: the code-segment program will have a QS
  439. EQU CS at the top of it; the stack-segment program will have QS
  440. EQU SS.  The source module can use QS as an override, just as if
  441. it were CS or SS.  The code would be, for example, QS MOV
  442. AL,VARNAME.
  443.  
  444.  
  445. The NIL Prefix
  446.  
  447. A86 provides a mnemonic, NIL, that generates no code.  NIL can be
  448. used as a prefix to another instruction (which will have no
  449. effect on that instruction), or it can appear by itself on a
  450. line.  NIL is provided to extend the example in the previous
  451. section, to cover the possibility of no overrides.  If your
  452. source module goes into a program that fits into 64K, so that all
  453. the segment registers have the same value, then code QS EQU NIL
  454. at the top of that program.
  455.  
  456.  
  457. Interrupt Equates
  458.  
  459. A86 allows you to equate your own name to an INT instruction with
  460. a specific interrupt number.  For example, if you place  TRAP EQU
  461. INT 3  at the top of your program, you can use the name TRAP as a
  462. synonym for INT 3  (the debugger trap on the 8086).
  463.  
  464.  
  465. Duplicate Definitions
  466.  
  467. A86 contains the unique feature of duplicate definitions.   We
  468. have already discussed local symbols, which can be redefined to
  469. different values without restriction.  Local symbols are the only
  470. symbols that can be redefined.  However, any symbol can be
  471. defined more than once, as long as the symbol is defined to be
  472. the same value and type in each definition.
  473.  
  474. This feature has two uses.  First, it eases modular program
  475. development.  For example, if two independently-developed source
  476. files both use the symbol ESC to stand for the ASCII code for
  477. ESCAPE, they can both contain the declaration ESC EQU 01B, with
  478. no problems if they are combined into the same program.
  479.                                                              9-10
  480.  
  481. The second use for this feature is assertion checking.  Your
  482. deliberate redeclaration of a symbol name is an assertion that
  483. the value of the symbol has not changed; and you want the
  484. assembler to issue you an error message if it has changed.
  485. Example: suppose you have declared a table of options in your
  486. DATA segment; and you have another table of initial values for
  487. those options in your CODE segment.  If you come back months
  488. later and add an option to your tables, you want to be reminded
  489. to update both tables in the same way.  You should declare your
  490. tables as follows:
  491.  
  492. DATA SEGMENT
  493.   OPTIONS:
  494.     .
  495.     .
  496.   OPT_COUNT EQU $-OPTIONS    ; OPT_COUNT is the size of the table
  497.  
  498. CODE SEGMENT
  499.   OPT_INITS:
  500.     .
  501.     .
  502.   OPT_COUNT EQU $-OPT_INITS  ; second OPT_COUNT had better be the same!
  503.  
  504.  
  505.  
  506. The = Directive
  507.  
  508. Syntax:  symbol-name = expression
  509.          symbol-name = built-in-symbol
  510.          symbol-name = INT n
  511.  
  512. The equals sign directive is provided for compatibility with That
  513. Other assembler.  It is identical to the EQU directive, with one
  514. exception: if the first time a symbol appears in a program is in
  515. an = directive, that symbol will be taken as a local symbol.  It
  516. can be redefined to other values, just like the generic local
  517. symbols (letter followed by digits) that A86 supports. (If you
  518. try to redefine an EQU symbol to a different value, you get an
  519. error message.) The = facility is most often used to define
  520. "assembler variables", that change value as the assembly
  521. progresses.
  522.  
  523.  
  524. The PROC Directive
  525.  
  526. Syntax:   name  PROC NEAR
  527.           name  PROC FAR
  528.           name  PROC
  529.  
  530. PROC is a directive provided for compatibility with Intel/IBM
  531. assemblers.  I don't like PROC; and I recommend that you do not
  532. use it, even if you are programming for those assemblers.
  533.                                                              9-11
  534.  
  535. The idea behind PROC is to give the assembler a mechanism whereby
  536. it can decide for you what kind of RET instruction you should be
  537. providing.  If you specify NEAR in your PROC directive, then the
  538. assembler will generate a near (same segment) return when it sees
  539. RET.  If you specify FAR in your PROC directive, the assembler
  540. will generate a far RETF return (which will cause both IP and CS
  541. to be popped from the stack).  If you simply leave well enough
  542. alone, and never code a PROC in your program, then RET will mean
  543. near return throughout your program.
  544.  
  545. The reason I don't like PROC is because it is yet another attempt
  546. by the assembler to do things "behind your back".  This goes
  547. against the reason why you are programming in assembly language
  548. in the first place, which is to have complete control over the
  549. code generated by your source program.  It leads to nothing but
  550. trouble and confusion.
  551.  
  552. Another problem with PROC is its verbosity.  It replaces a simple
  553. colon, given right after the label it defines.  This creates a
  554. visual clutter in the program, that makes the program harder to
  555. read.
  556.  
  557. Even if you are programming in that other assembler, and you need
  558. to code a far return, I recommend that you create a RETF macro
  559. (it would have the single line DB 0CBH), and stay away from PROCs
  560. entirely.
  561.  
  562.  
  563. The ENDP Directive
  564.  
  565. Syntax:  [name] ENDP
  566.  
  567. The only action A86 takes when it sees an ENDP directive is to
  568. return the assembler to its (sane) default state, in which RET is
  569. a near return.
  570.  
  571. NOTE that this means that A86 does not support nested PROCs, in
  572. which anything but the innermost PROC has the FAR attribute.  I'm
  573. sorry if I am blunt, but anybody who would subject their program
  574. to that level of syntactic clutter has rocks in their head.
  575.  
  576.  
  577. The LABEL Directive
  578.  
  579. Syntax:  name LABEL NEAR
  580.          name LABEL FAR
  581.          name LABEL BYTE
  582.          name LABEL WORD
  583.  
  584. LABEL is another directive provided for compatibility with
  585. Intel/IBM assemblers.  A86 provides less verbose ways of
  586. specifying all the above LABEL forms, except for LABEL FAR.
  587.  
  588. LABEL defines "name" to have the type given, and a value equal to
  589. the current output pointer.  Thus, LABEL NEAR is synonymous with
  590. a simple colon following the name; and LABEL BYTE and LABEL WORD
  591. are synonymous with DB and DW, respectively, with no operands.
  592.                                                              9-12
  593.  
  594. LABEL FAR does have a unique functionality, not found in other
  595. assemblers.  It identifies "name" as a procedure that can be
  596. called from outside this program's code segment.  Such procedures
  597. should have RETFs instead of RETs. Furthermore, I have provided
  598. the following feature, unique to A86: if you CALL the procedure
  599. from within your program, A86 will generate a PUSH CS instruction
  600. followed by a NEAR call to the procedure.  Other assemblers will
  601. generate a FAR call, having the same functional effect; but the
  602. FAR call consumes more program space, and takes more time to
  603. execute.
  604.  
  605. WARNING: you cannot use the above CALL feature as a forward
  606. reference; the LABEL FAR definition must precede any CALLs to it.
  607. This is unavoidable, since the assembler must assume that a CALL
  608. to an undefined symbol takes 3 program bytes.  All assemblers
  609. will issue an error in this situation.
  610.  
  611.